﻿using DailyPoetryM.Models;
using System.Linq.Expressions;
using SQLite;

namespace DailyPoetryM.Services;
public class PoetryStorage : IPoetryStorage
{
    public const string DbName = "poetrydb.sqlite3";
    /// <summary>
    /// 数据库文件存放的路径
    /// </summary>
    public static readonly string PoetryDbPath =
        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DbName);

    private IPreferenceStorage _preferenceStorage;
    public PoetryStorage(IPreferenceStorage preferenceStorage)
    {
        _preferenceStorage = preferenceStorage;
    }
    private SQLiteAsyncConnection _connection;
    public SQLiteAsyncConnection Connection =>
        _connection ??= new SQLiteAsyncConnection(PoetryDbPath);//打开数据库连接

    public bool IsInitialized =>
        _preferenceStorage.Get(PoetryStorageConstant.VersionKey, 0) == PoetryStorageConstant.Version;
    /// <summary>
    /// 根据id获取诗歌信息
    /// </summary>
    /// <param name="id">诗歌ID</param>
    /// <returns></returns>
    public async Task<Poetry> GetPoetryAsync(int id)
    {
        return await Connection.Table<Poetry>().FirstOrDefaultAsync(p => p.Id == id);
    }

    /// <summary>
    /// 根据查询条件获取诗词列表
    /// </summary>
    /// <param name="where">查询条件</param>
    /// <param name="skip">跳过多少记录</param>
    /// <param name="take">取多少记录</param>
    /// <returns></returns>
    public async Task<IEnumerable<Poetry>> GetPoetriesAsync(Expression<Func<Poetry, bool>> where, int skip, int take)
    {
        return await Connection.Table<Poetry>().Where(where)
            .Skip(skip)  //跳过多少记录
            .Take(take)  //取多少记录
            .ToListAsync();
    }
    /// <summary>
    /// 初始化数据库
    /// </summary>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task InitializeAsync()
    {
        //打开文件，自动关闭资源
        await using var dbFileStream = new FileStream(PoetryDbPath, FileMode.OpenOrCreate);
        //打开资源
        await using var dbAssetStream =
            typeof(PoetryStorage) //Type
            .Assembly             //Assembly
            .GetManifestResourceStream(DbName)
            ?? throw new Exception($"找不到名为{DbName}的资源");

        //复制文件
        await dbAssetStream.CopyToAsync(dbFileStream);

        //初始化好后，要存版本号
        _preferenceStorage.Set(PoetryStorageConstant.VersionKey, PoetryStorageConstant.Version);
    }

    /// <summary>
    /// 关闭数据库
    /// </summary>
    /// <returns></returns>
    public async Task CloseAsync() => await Connection.CloseAsync();
}

/// <summary>
/// 诗词存储常量类
/// </summary>
public static class PoetryStorageConstant
{
    /// <summary>
    /// 最新的数据库版本
    /// </summary>
    public const int Version = 1;
    /// <summary>
    /// 偏好存储中存的数据库版本对应的 Key
    /// </summary>
    public const string VersionKey = nameof(PoetryStorageConstant) + "." + nameof(Version);//PoetryStorageConstant.Version,这种就不是硬编码的方式
}
